/**
 * 高德地图通用的配置文件
 */
/*  eslint-disable */
import AMapLoader from '@amap/amap-jsapi-loader'

const ENV = import.meta.env
const { VITE_APP_MODE, VITE_BASE_URL } = ENV
const isDev = VITE_APP_MODE === 'develop' ||  VITE_APP_MODE === 'mock'

/**
  * 配置信息
  * @returns <Object>
  */
export async function getConfig() {
  // 服务器环境，设置白名单
  if (!isDev) {
    const { host, protocol } = window.location
    // 后续调的时候，再放开
    const serviceHost = `${protocol}//${host}/_AMapService`
    // eslint-disable-next-line
    window._AMapSecurityConfig = {
      serviceHost: serviceHost,
    }
    console.log('serviceHost', serviceHost)
  }

  // 注意（您在2021年12月02日申请以后的key需要配合您的安全密钥一起使用）
  // 1.x是以前的, https://lbs.amap.com/api/jsapi-v2/guide/abc/load
  const privite_key = 'a4df1b5a57b9ba3e9be795464b7009ac' // 这个是网上搜索的，应该是1.x版本之前的
  // const privite_key = 'a4df1b5a57b9ba3e9be795464b7009ac' // 网上搜的1.x的版本 以上两个privite_key都可以使用
  const enterprise_key = "d222072be5d865866cb4edd970b438f7"; // 公司企业版 公钥key, 私钥在NG层
  // const enterprise_key = "87ec92d2d74f8e87f340ce1c8024133fa8"
  // const enterprise_key = "7ec92d2d74f8e87f340ce1c8024133fa"
  const key = isDev ? privite_key : enterprise_key // 这块先用 privite_key
  console.log('key: ', key)
  const config = await new Promise((resolve) => {
    resolve({
      key,
      version: '2.0'
    })
  })
  return config
}

/**
 * 插件配置
 * @param {*} plugins 插件列表数据
 * @param {*} AMap AMap实例
 * @returns
 */
function pluginHandler(plugins: any, AMap: any) {
  return new Promise((resolve, reject) => {
    AMap.plugin(plugins, (result: any) => {
      resolve({
        success: true,
        data: result
      })
    }, (e: any) => {
      console.log(e)
      reject(new Error('加载插件出错了...'))
    })
  })
}

export { pluginHandler }

/**
 *
 * @returns
 */
async function commonGeoCoderHandler(AMap: any) {
  // 1. 加载逆地理编码插件
  const result: any = await pluginHandler(['AMap.Geocoder'], AMap)
  const { success, data } = result
  if (!success) return console.log(data)
  // 2. 实例化地理编码
  const geocoder = new AMap.Geocoder({
    radius: 1000, // 以已知坐标为中心点，radius为半径，返回范围内兴趣点和道路信息
    extensions: 'all' // 返回地址描述以及附近兴趣点和道路信息，默认“base”
  })
  return geocoder
}
/**
 *
 * @param {*} mapObj map实例
 * @param {*} AMap AMap实例
 * @param {*} position 位置信息
 * @param {*} completeFn 完成回调
 * @returns
 */
async function geoCoderHandler(mapObj: any, AMap: any, position: any, completeFn: Function) {
  // 1. 加载逆地理编码插件 2. 实例化地理编码
  const geocoder = await commonGeoCoderHandler(AMap)
  // 3. 先清理
  mapObj.clearMap()
  // 4. 设置标记的位置
  const marker = new AMap.Marker()
  marker.setMap(mapObj)
  marker.setPosition(position)
  // 5. 基于经纬度进行逆地理编码
  const { lng, lat } = position
  geocoder.getAddress(new AMap.LngLat(lng, lat))
  // 6. 事件监听
  geocoder.on('complete', (e: any) => {
    const isOk = e.info === 'OK'
    const name = !isOk ? '' : e.regeocode.formattedAddress
    const result = { name, lng, lat }
    void (completeFn && completeFn(result))
  })
}

export { geoCoderHandler }

/**
 * 逆地理编码
 * @param {*} AMap AMap实例
 * @param {*} LngLat 经纬度
 */
export async function pureRegeoCoder(AMap: any, LngLat: any) {
  const geocoder = await commonGeoCoderHandler(AMap)
  return new Promise((resolve, reject) => {
    geocoder.getAddress(LngLat, (status: string, e: any) => {
      if (status === 'complete' && e.info === 'OK') {
        resolve(e.regeocode.formattedAddress)
      } else {
        reject(new Error(e))
      }
    })
  })
}

/**
 * 地图加载器封装
 * @param {*} config 配置文件
 * @returns {Promise}
 */
export function aMapLoaderHandler(config: any) {
  return new Promise((resolve, reject) => {
    AMapLoader.load(config)
      .then((AMap: any) => {
        resolve({
          success: true,
          data: AMap
        })
      }).catch((e: any) => {
        reject(new Error('配置文件加载出错了...'))
      })
  })
}

/**
 * 地图容器初始化
 * @param {*} AMap AMap实例
 * @param {*} container 容器id
 * @returns {AMap.Map}
 */
export function mapContainerInit(AMap: any, container: any) {
  const option = {
    resizeEnable: true,
    zoom: 15 // 地图显示的缩放级别
  }
  return new AMap.Map(container, option)
}

/**
 * 配置比例尺缩放
 * @param {*} mapObj map实例
 * @param {*} AMap AMap实例
 */
export async function scaleSettingHandler(mapObj: any, AMap: any) {
  const result: any = await pluginHandler(['AMap.Scale'], AMap)
  const { success, data } = result
  if (!success) {
    console.log(data)
    return
  }
  const scale = new AMap.Scale({})
  mapObj.addControl(scale)
}

/**
 * 配置工具条
 * @param {*} mapObj map实例
 * @param {*} AMap AMap实例
 */
export async function toolBarSettingHandler(mapObj: any, AMap: any) {
  const result: any = await pluginHandler(['AMap.ToolBar'], AMap)
  const { success, data } = result
  if (!success) {
    console.log(data)
    return
  }
  const tool = new AMap.ToolBar()
  mapObj.addControl(tool)
}

/**
 * 配置定位
 * @param {*} mapObj map实例
 * @param {*} AMap AMap实例
 * @param {*} successFn 定位成功回调
 * @param {*} failFn 定位失败回调
 */
export async function geoLocationHandler(mapObj: any, AMap: any, successFn: Function, failFn: Function) {
  const result: any = await pluginHandler(['AMap.Geolocation'], AMap)
  const { success, data } = result
  if (!success) {
    console.log(data)
    return
  }
  const options = {
    enableHighAccuracy: true, // 是否使用高精度定位，默认：true
    convert: true,
    showMarker: true,
    panToLocation: true,
    timeout: 10000,
    zoomToAccuracy: true, // 定位成功后是否自动调整地图视野到定位点
    position: 'LT', // 位置信息
  }
  const geolocation = new AMap.Geolocation(options)
  mapObj.addControl(geolocation)
  geolocation.getCurrentPosition((status: string, res: any) => {
    console.log('status res', status, res) // 这个log不要去掉，可以排查定位失败问题
    if (status === 'complete') {
      const { position } = res
      // 从经纬度获取地址信息
      geoCoderHandler(mapObj, AMap, position, successFn)
      return
    }
    void (failFn && failFn({
      name: '',
      lng: '',
      lat: ''
    }))
  })
}

/**
 * 基于当前经纬度，定位到当前位置
 * @param {*} mapObj map实例
 * @param {*} AMap AMap实例
 * @param {*} locationInfo 当前位置
 */
export async function designativeLocationHandler(mapObj: any, AMap: any, locationInfo: any) {
  if (!(locationInfo.lng && mapObj && AMap)) return
  // 设置标记的位置
  const marker = new AMap.Marker()
  marker.setMap(mapObj)
  const { lng, lat } = locationInfo
  marker.setPosition([lng, lat])
  mapObj.setFitView() // 执行定位
}

/**
 * 配置POI搜索
 * @param {*} mapObj map实例
 * @param {*} AMap AMap实例
 * @param {*} inputId 搜索input对应的id
 * @param {*} selectFn 点击选择后的回调
 */
export async function poiSearchHandler(mapObj: any, AMap: any, inputId: string, selectFn: Function) {
  // 1. 加载插件
  const result: any = await pluginHandler(['AMap.PlaceSearch', 'AMap.AutoComplete'], AMap)
  const { success, data } = result
  if (!success) {
    console.log(data)
    return
  }
  // 2. 输入提示
  const autoOptions = {
    input: inputId
  }
  // 3. 自动完成
  const auto = new AMap.AutoComplete(autoOptions)
  // 4. 搜索
  const placeSearch = new AMap.PlaceSearch({
    map: mapObj
  })
  // 5. 注册选择监听，当选中某条记录时会触发
  auto.on('select', (e: any) => {
    const { poi } = e
    const {
      location, adcode, name, district
    } = poi
    placeSearch.setCity(adcode)
    placeSearch.search(name) // 关键字查询查询
    const resultData = {
      name: district + name,
      lng: location.lng,
      lat: location.lat
    }
    void (selectFn && selectFn(resultData))
  })
}

// 配置地图点击监听
export function mapClickListener(mapObj: any, AMap: any, completeFn: any) {
  // 为地图注册 click 事件获取鼠标点击出的经纬度坐标
  mapObj.on('click', (e: any) => {
    // 从经纬度获取地址信息
    geoCoderHandler(mapObj, AMap, e.lnglat, completeFn)
  })
}
